<?php

class Admin_VirtualmachineController extends Zend_Controller_Action {

    private $_logger;
    private $_errorLogger;

    public function init() {
        /* Initialize action controller here */
        $this->_logger = Zend_Registry::get(VirtualLabs_Common::DEBUG_LOG);
        $this->_errorLogger = Zend_Registry::get(VirtualLabs_Common::ERROR_LOG);
    }

    public function preDispatch() {
        // Autenticacion del usuario
        $auth = Zend_Auth::getInstance();
        if (!$auth->hasIdentity()) {
            $this->_helper->layout->disableLayout();
            $this->_forward("index", "index", "");
        } else {
            $identity = $auth->getIdentity();
            if ($identity['tipo_usuario'] != VirtualLabs_Admin_Usuario::ROL_ADMIN) {
                $this->_helper->layout->disableLayout();
                $this->_redirect('/');
            }
        }
        //fin de la autenicacion del usuario
    }

    public function indexAction() {
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_helper->layout->disableLayout();
    }

    public function labAction() {
        // action body
        $codLab = $this->getRequest()->getParam("laboratorio");
        $this->view->laboratorio = $codLab;
        $labDao = new VirtualLabs_Admin_Laboratorio();
        $lab = $labDao->getLaboratorio(array('codigo_laboratorio', 'nombre'), array('codigo_laboratorio' => array('criteria' => '=', 'value' => $codLab)));
        $this->view->nombreLab = $lab['nombre'];
    }

    public function listbylabAction() {
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_helper->layout->disableLayout();

        $laboratorio = $this->getRequest()->getParam("laboratorio");
        $vm = new VirtualLabs_Admin_Machine();
        $vmCloudstack = new VirtualLabs_Rest_VirtualLabs_VirtualMachine();
        $response = array();
        try {
            $vmList = $vm->getVirtualMachinesByLab($laboratorio);
            foreach ($vmList as $value) {
                if (isset($value['codigo_vm'])) {
                    $vmCloudData = Zend_Json_Decoder::decode($vmCloudstack->listVM($value['codigo_vm']));
                    if (!isset($vmCloudData['listvirtualmachinesresponse']['errorcode'])) {

                        #$response[] = array("<a href='/admin/virtualmachine/deletevm/codigo_maquina_virtual/{$value['codigo_maquina_virtual']}' title='Eliminar Maquina Virtual'><img src=\"/images/delete.png\"></a>",
                        $response[] = array($value['codigo_maquina_virtual'],
                            "<input type='image' src='/images/trash-icon-40x40.png' onclick='deletevm({$value['codigo_maquina_virtual']});' title='Eliminar Maquina Virtual' />",
//                            "<a href='/admin/virtualmachine/vm/codigo_maquina_virtual/{$value['codigo_maquina_virtual']}'>{$vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['name']}</a>",
                            "<strong>{$vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['name']}</strong>",
//                            "<a href='/admin/virtualmachine/vmassign/codigo_maquina_virtual/{$value['codigo_maquina_virtual']}' title='Asignar Alumnos'><img src='" . $this->view->baseUrl() . "/images/users/Users-Group-icon2.png" . "'/></a>",
                            $vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['templatedisplaytext'],
                            $vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['serviceofferingname'],
                            $vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['nic'][0]['ipaddress'],
                            $vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['nic'][0]['netmask'],
                            $value['estado']);
                    } else {
                        $response[] = array($value['codigo_maquina_virtual'],
                            "<input type='image' src='/images/delete.png' onclick='deletevm({$value['codigo_maquina_virtual']});' title='Eliminar Maquina Virtual' />",
                            "<a href='#'>NOT READY</a>",
                            "",
                            "",
                            "",
                            "",
                            "",
                            $value['estado']);
                    }
                } else {
                    $response[] = array($value['codigo_maquina_virtual'],
                        "<input type='image' src='/images/delete.png' onclick='deletevm({$value['codigo_maquina_virtual']});' title='Eliminar Maquina Virtual' />",
                        "<a href='#'>NOT READY</a>",
                        "",
                        "",
                        "",
                        "",
                        "",
                        $value['estado']);
                }
            }
        } catch (Exception $exc) {
            echo $exc->getTraceAsString();
            $aaData = array("error" => $exc->getTraceAsString());
        }
        $this->_logger->debug("perfilEncedidoDao : " . print_r($aaData, TRUE));
        $aaData = array("aaData" => $response);
        echo Zend_Json_Encoder::encode($aaData);
    }

    public function vmAction() {
        $vmDao = new VirtualLabs_Admin_Machine();
        $vm = $vmDao->getVirtualMachine(array('codigo_vm', 'codigo_perfil_encendido', 'codigo_laboratorio'), array('codigo_maquina_virtual' => array('criteria' => '=', 'value' => $this->getRequest()->getParam('codigo_maquina_virtual'))));
        $perfilEncedidoDao = new VirtualLabs_Admin_PerfilEncendido();
        $labDao = new VirtualLabs_Admin_Laboratorio();
        $laboratorio = $labDao->getLaboratorio('*', array('codigo_laboratorio' => array('criteria' => '=', 'value' => $vm['codigo_laboratorio'])));
        $perfilEncendido = $perfilEncedidoDao->getPerfilEncendido('*', array('codigo_perfil_encendido' => array('criteria' => '=', 'value' => $vm['codigo_perfil_encendido'])));

//        $this->debugLog->debug("perfilEncedidoDao : " . print_r($perfilEncendido));

        $cloudData = $vmDao->getVmData($vm['codigo_vm']);
        $this->_logger->debug("cloudData : $cloudData");
        $vmCloudSummary = array('id' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['id'],
            'name' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['name'],
            'displayname' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['displayname'],
            'hostid' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['hostid'],
            'hostname' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['hostname'],
            'instancename' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['instancename'],
            'state' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['state'],
            'cpuspeed' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['cpuspeed'],
            'cpunumber' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['cpunumber'],
            'serviceofferingname' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['serviceofferingname'],
            'memory' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['memory'],
            'ipaddress' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['nic'][0]['ipaddress'],
            'networkname' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['nic'][0]['networkname'],
            'netmask' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['nic'][0]['netmask'],
            'gateway' => $cloudData['listvirtualmachinesresponse']['virtualmachine'][0]['nic'][0]['gateway']);
        $cloudToString = print_r($vmCloudSummary, true);
        $this->_logger->debug("cloudToString : " . $cloudToString);
        if ($vm) {
            $this->view->codigo_maquina_virtual = $this->getRequest()->getParam('codigo_maquina_virtual');
            $this->view->displayname = $vmCloudSummary['displayname'];
            $this->view->codigo_vm = $vmCloudSummary['id'];
            $this->view->cpuSpeed = $vmCloudSummary['cpuspeed'];
            $this->view->cpuNumber = $vmCloudSummary['cpunumber'];
            $this->view->memory = $vmCloudSummary['memory'];
            $this->view->networkName = $vmCloudSummary['networkname'];
            $this->view->ip = $vmCloudSummary['ipaddress'];
            $this->view->gateway = $vmCloudSummary['gateway'];
            $this->view->netmask = $vmCloudSummary['netmask'];
            $this->view->instanceName = $vmCloudSummary['instancename'];
            $this->view->hostName = $vmCloudSummary['hostname'];
            $this->view->state = strtolower($vmCloudSummary['state']);

            // perfil encendido
            $this->view->dias = $perfilEncendido['dias_encendido'];
            $this->view->horaInicioDia = $perfilEncendido['hora_inicio_dia'];
            $this->view->horaFinDia = $perfilEncendido['hora_fin_dia'];
            $this->view->horasDiarias = $perfilEncendido['horas_utilizacion_diario'];
            $this->view->horasCurso = $perfilEncendido['horas_utilizacion_curso'];
            $this->view->fueraHorario = ($perfilEncendido['permite_fuera_horario'] == 'N') ? 'No' : 'S&iacute;';

//            laboratorio
            $this->view->nombreLaboratorio = $laboratorio['nombre'];
            $this->view->codigoLaboratorio = $laboratorio['codigo_laboratorio'];

//            invocamos al script para datos del hypervisor para VNC
            $this->_logger->debug(VirtualLabs_Script_Bash::BASH_INTERPRETER . " " . SCRIPT_PATH . VirtualLabs_Script_Bash::VM_VNC_DISPLAY_NUMBER . " {$vmCloudSummary['hostname']} {$vmCloudSummary['instancename']} ");
            ob_start();
            $this->view->port = system(VirtualLabs_Script_Bash::BASH_INTERPRETER . " " . SCRIPT_PATH . VirtualLabs_Script_Bash::VM_VNC_DISPLAY_NUMBER . " {$vmCloudSummary['hostname']} {$vmCloudSummary['instancename']} ");
            ob_clean();
        } else {
            echo '';
        }
    }

    public function managevmAction() {
        $this->_helper->layout->disableLayout();
        $this->view->port = $this->getRequest()->getParam('port');
        $this->view->hostName = $this->getRequest()->getParam('hostname');
    }

    public function checkdeployjobstatusAction() {
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_helper->layout->disableLayout();
        $codigoLaboratorio = $this->getRequest()->getParam("codigo_laboratorio");
        $flag = FALSE;
        $util = new VirtualLabs_Rest_Util();
        $vmDao = new VirtualLabs_Admin_Machine();
        $vmList = $vmDao->getVirtualMachines(array('async_job_id', 'codigo_maquina_virtual'), array('estado' => array('criteria' => '=', 'value' => VirtualLabs_Admin_Machine::ESTADO_CREACION),
            'codigo_laboratorio' => array('criteria' => '=', 'value' => $codigoLaboratorio)));
        $response = array();

        foreach ($vmList as $vm) {
            $flag = TRUE;
            $responseCheck = $util->jobStatus($vm['async_job_id']);
            if (isset($responseCheck['queryasyncjobresultresponse']['jobresult']['errorcode'])) {
                $data = array('estado' => 'E');
                $vmDao->save(VirtualLabs_Admin_Machine::TABLE_NAME, $data, array('key' => 'codigo_maquina_virtual', 'value' => $vm['codigo_maquina_virtual']));
            } else if (isset($responseCheck['queryasyncjobresultresponse']['jobresult']['virtualmachine']['id'])) {
                $data = array('codigo_vm' => $responseCheck['queryasyncjobresultresponse']['jobresult']['virtualmachine']['id'], 'estado' => 'A');
                $vmDao->save(VirtualLabs_Admin_Machine::TABLE_NAME, $data, array('key' => 'codigo_maquina_virtual', 'value' => $vm['codigo_maquina_virtual']));
            }
        }

        if ($flag) {
            $response = array('response' => 'refresh');
        } else {
            $response = array('response' => 'stop');
        }
        echo Zend_Json_Encoder::encode($response);
    }

    public function viewconsoleAction() {
//        $this->_helper->viewRenderer->setNoRender(true);
//        $this->_helper->layout->disableLayout();

        $login = new VirtualLabs_Rest_Login();
        $loginResponse = $login->login("admin", md5("master"));

        $sessionKey = $loginResponse['loginresponse']['sessionkey'];
        foreach ($loginResponse['loginresponse'] as $key => $value) {
            setcookie(urlencode($key), trim(urlencode($value)), 0, "/", "virtual-labs.org");
        }

        $config = new Zend_Config_Ini(CLOUDSTACK_CONFIG_FILE, APPLICATION_ENV);
        $endPoint = $config->get("console_endpoint");
        echo "<a href='$endPoint" . "cmd=access&sessionkey=$sessionKey&vm=" . $this->getParam("vm") . "'>Access</a>";
    }

    public function encendervmAction() {
        $this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        $vm = new VirtualLabs_Admin_Machine();
        if ($this->permiteEncender($this->getRequest()->getParam('codigo_vm'))) {
            $encenderResponse = $vm->encenderVM($this->getRequest()->getParam('codigo_vm'));
            $encenderResponseString = print_r($encenderResponse, true);
            $this->_logger->debug("encenderResponse : $encenderResponseString");
            if ($encenderResponse["startvirtualmachineresponse"]["jobid"]) {
                echo Zend_Json_Encoder::encode(array('response' => array('jobid' => $encenderResponse["startvirtualmachineresponse"]["jobid"])));
            } else {
                echo Zend_Json_Encoder::encode(array('response' => 'error'));
            }
        } else {
            echo Zend_Json_Encoder::encode(array('response' => 'error', 'message' => 'No es posible encender la maquina. Verifique el horario de encendido'));
        }
    }

    public function apagarvmAction() {
        $this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        $vm = new VirtualLabs_Admin_Machine();
        $apagarResponse = $vm->apagarVM($this->getRequest()->getParam('codigo_vm'));
        $apagarResponseString = print_r($apagarResponse, true);
        $this->_logger->debug("apagarResponse : $apagarResponseString");
        if ($apagarResponse["stopvirtualmachineresponse"]["jobid"]) {

            echo Zend_Json_Encoder::encode(array('response' => array('jobid' => $apagarResponse["stopvirtualmachineresponse"]["jobid"])));
        } else {
            echo Zend_Json_Encoder::encode(array('response' => 'error'));
        }
    }

    public function checkvmstatusAction() {
        $this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        $id = $this->getParam('jobid');
        if (!$id)
            return;
        $restUtil = new VirtualLabs_Rest_Util();
        try {
            $vmCloudData = $restUtil->jobStatus($id);
            $vmCloudDataToString = print_r($vmCloudData, true);
            $this->_logger->debug($vmCloudDataToString);
            if (VirtualLabs_Rest_Util::STOP_VM_CMD == $vmCloudData['queryasyncjobresultresponse']['cmd']) {
                $this->_logger->debug("estado-sttoped : " . strtolower($vmCloudData['queryasyncjobresultresponse']['jobresult']['virtualmachine']['state']));
                if (strtolower($vmCloudData['queryasyncjobresultresponse']['jobresult']['virtualmachine']['state']) == VirtualLabs_Admin_Machine::ESTADO_POWEROFF) {
                    echo Zend_Json_Encoder::encode(array('response' => 'OK'));
                } else {
                    echo Zend_Json_Encoder::encode(array('response' => 'ERROR'));
                }
            } else if (VirtualLabs_Rest_Util::START_VM_CMD == $vmCloudData['queryasyncjobresultresponse']['cmd']) {
                $this->_logger->debug("estado-running : " . strtolower($vmCloudData['queryasyncjobresultresponse']['jobresult']['virtualmachine']['state']));
                if (strtolower($vmCloudData['queryasyncjobresultresponse']['jobresult']['virtualmachine']['state']) == VirtualLabs_Admin_Machine::ESTADO_ENCENDIDO) {
                    echo Zend_Json_Encoder::encode(array('response' => 'OK'));
                } else {
                    echo Zend_Json_Encoder::encode(array('response' => 'ERROR'));
                }
            }
        } catch (Exception $e) {
            $this->_logger->err($e->getMessage());
            $this->_logger->err($e->getTraceAsString());
        }
    }

    private function permiteEncender($codigoVM) {
        $dayWeek = array(
            'Mon' => 'Lu',
            'Tue' => 'Ma',
            'Wed' => 'Mi',
            'Thu' => 'Ju',
            'Fri' => 'Vi',
            'Sat' => 'Sa',
            'Sun' => 'Do'
        );
        $retval = false;
        $vmDao = new VirtualLabs_Admin_Machine();
        $peDao = new VirtualLabs_Admin_PerfilEncendido();
        //recuperamos el codigo de la maquina virtual y el codigo del perfil de encendido para efectivamente obtener luego el perfil de encendido
        $vm = $vmDao->getVirtualMachine(array('codigo_maquina_virtual', 'codigo_perfil_encendido'), array('codigo_vm' => array('criteria' => '=', 'value' => $codigoVM)));

        //una vez obtenido el codigo de perfil encendido obtener datos de la tabla perfil_encendido
        $pe = $peDao->getPerfilEncendido(array('codigo_perfil_encendido', 'dias_encendido', 'hora_inicio_dia', 'hora_fin_dia', 'horas_utilizacion_diario', 'horas_utilizacion_curso', 'permite_fuera_horario'), array('codigo_perfil_encendido' => array('criteria' => '=', 'value' => $vm['codigo_perfil_encendido'])));

        $today = $dayWeek[date('D')];
        //Verificamos si permite fuera de horario                              
        if ($pe['permite_fuera_horario'] == 'N') {
            //verificar si permite el dia de hoy verificando si el 
            $pos = strpos($pe['dias_encendido'], $today);
            if ($pos === FALSE) {
                //No permite prender el dia de hoy
                $retval = false;
            } else {
                //verificar si puede prenderse en el horario..             
                $hora_inicio = strtotime(date("Y-m-d") . " " . $pe['hora_inicio_dia']);
                $hora_fin = strtotime(date("Y-m-d") . " " . $pe['hora_fin_dia']);
                $hora_actual = strtotime(date("Y-m-d H:i:s"));
//               $this->debugLog->debug("Hora inicio: " . $hora_inicio);
//               $this->debugLog->debug("Hora fin: " . $hora_fin);
//               $this->debugLog->debug("Hora actual: " . $hora_actual);
                if (($hora_fin >= $hora_actual) && ($hora_actual >= $hora_inicio)) {
                    $this->debugLog->debug("Es posible prender la maquina!! ");
                    $retval = true;
                } else {
                    $retval = false;
                }
            }
        } else {
            $this->debugLog->debug("Permite fuera de horario");
            $retval = true;
        }

        return $retval;
    }

    public function vmassignAction() {
        // action body
        $codVM = $this->getRequest()->getParam("codigo_maquina_virtual");
        $this->_logger->debug("codigo vm = " . $codVM);
        $this->view->codigo_vm = $codVM;

        //consultar los datos de la VM
        $vmDao = new VirtualLabs_Admin_Machine();
        $vm = $vmDao->getVirtualMachine(array('codigo_maquina_virtual', 'codigo_vm', 'codigo_laboratorio'), array('codigo_maquina_virtual' => array('criteria' => '=', 'value' => $codVM)));

        $vmCloudstack = new VirtualLabs_Rest_VirtualLabs_VirtualMachine();
        $vmCloudData = Zend_Json_Decoder::decode($vmCloudstack->listVM($vm['codigo_vm']));
        $this->view->vmdisplayname = "Virtual Machine: " . $vmCloudData['listvirtualmachinesresponse']['virtualmachine'][0]['displayname'];

        //datos del laboratorio
        $labDao = new VirtualLabs_Admin_Laboratorio();
        $lab = $labDao->getLaboratorio(array('codigo_laboratorio', 'nombre'), array('codigo_laboratorio' => array('criteria' => '=', 'value' => $vm['codigo_laboratorio'])));
        $this->view->labname = "Laboratorio " . $lab['nombre'];
        $this->view->codigo_laboratorio = $lab['codigo_laboratorio'];
    }

    public function vmassignsaveAction() {
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_helper->layout->disableLayout();
        $students = $this->getRequest()->getParam("students"); //array
        $codigo_vm = $this->getRequest()->getParam("codigo_vm"); //array
        //Eliminar todos los usuarios asignados a la tabla maquina_virtual_usuario
        $codigoVM = array('key' => 'codigo_maquina_virtual', 'value' => $codigo_vm);
        $vmDao = new VirtualLabs_Admin_Machine();
        $this->_logger->debug("Students = " . print_r($students, TRUE));
        try {
            $vmDao->deleteMiembrosAsociadosVM($codigoVM);
            if (!empty($students)) {
                foreach ($students as $student) {
                    $vmDao->insertMiembroAsociado($codigo_vm, $student);
                }
            }
            echo Zend_Json_Encoder::encode(array('response' => 'success'));
        } catch (Exception $e) {
            echo Zend_Json_EncoFder::encode(array('response' => 'error', 'message' => $e->getMessage()));
        }
    }

    public function deletevmAction() {
        //no olvidar de hacer el chequeo de que el usuario puede hacer eso
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_helper->layout->disableLayout();
        $codigo_maquina_virtual = $this->getRequest()->getParam("codigo_maquina_virtual");

        $vmDao = new VirtualLabs_Admin_Machine();
        $vm = $vmDao->getVirtualMachine(array('codigo_vm', 'async_job_id',), array('codigo_maquina_virtual' => array('criteria' => '=', 'value' => $codigo_maquina_virtual)));
        //$util = new VirtualLabs_Rest_Util();

        $this->_logger->debug("vamos a borrar la maquina con codigo: " . $codigo_maquina_virtual . " y codigo_cloud: " . $vm['codigo_vm']);

        try {
            //se borra de la base de datos la maquina virtual
            $vmRest = new VirtualLabs_Rest_VirtualLabs_VirtualMachine();
            $vmRest->deleteVM($vm["codigo_vm"]);

            //se borran los estudiantes asignados a la vm            
            $codigoVM = array('key' => 'codigo_maquina_virtual', 'value' => $codigo_maquina_virtual);
            $vmDao->deleteMiembrosAsociadosVM($codigoVM);
            $vmDao->deleteVM($codigoVM);
            echo Zend_Json_Encoder::encode(array('response' => 'success', 'codigo_maquina_virtual' => $codigo_maquina_virtual));
        } catch (Exception $e) {
            echo Zend_Json_Encoder::encode(array('response' => 'error', 'message' => $e->getMessage()));
        }
    }

}